/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.icee.myth.utils;

import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

/**
 *
 * @author liuxianke
 */
public class AESUtil {

    public static void generateKey(String keyfile) {
        try {
            KeyGenerator keygen = KeyGenerator.getInstance("AES");
            SecureRandom random = new SecureRandom();
            keygen.init(random);
            SecretKey key = keygen.generateKey();

            ObjectOutputStream out = new ObjectOutputStream(
                    new FileOutputStream(keyfile));
            out.writeObject(key);
            out.flush();
            out.close();
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
        } catch (FileNotFoundException fileNotFoundEx) {
            fileNotFoundEx.printStackTrace();
        } catch (IOException ioEx) {
            ioEx.printStackTrace();
        }
    }

    public static SecretKey loadKey(byte[] data) {
        ObjectInputStream in = null;
        SecretKey key = null;
        try {
            in = new ObjectInputStream(new ByteArrayInputStream(data));
            key = (SecretKey) in.readObject();
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return key;
    }

    public static void main(String[] args) {
        ObjectOutputStream out = null;
        try {
            SecretKey key = AESKey.key;
            out = new ObjectOutputStream(new FileOutputStream("mkey"));
            out.write(key.getEncoded());
            out.flush();
            out.close();
        } catch (IOException ex) {
            Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                out.close();
            } catch (IOException ex) {
                Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public static byte[] encryptToBytes(String keystr, String str) {
        if(keystr==null || str == null)
            return null;
        SecretKeySpec keyspec = new SecretKeySpec(keystr.getBytes(), "AES");
        return encryptToBytes(keyspec, str);
    }

    public static byte[] encryptToBytes(String keystr, byte[] contents) {
        if(keystr==null || contents == null)
            return null;
        SecretKeySpec keyspec = new SecretKeySpec(keystr.getBytes(), "AES");
        return encryptToBytes(keyspec, contents);
    }

    public static byte[] encryptToBytes(SecretKey key, String str) {
        if(key == null || str == null)
            return null;

        try {
            return encryptToBytes(key, str.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException ex) {
            ex.printStackTrace();
            return null;
        }
    }

    public static byte[] encryptToBytes(SecretKey key, byte[] contents) {
        if(key == null || contents == null)
            return null;

        try {
//            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, key);
// TODO: do this           byte[] res = cipher.doFinal(contents);
            byte[] res = contents;
            return res;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public static String encryptToString(String keystr, String str) {
        if(keystr == null || str == null)
            return null;
        
        SecretKeySpec keyspec = new SecretKeySpec(keystr.getBytes(), "AES");
        return encryptToString(keyspec, str.getBytes());
    }

    public static String encryptToString(SecretKey key, String str) {
        if(key == null || str == null)
            return null;

        return encryptToString(key, str.getBytes());
    }

    public static String encryptToString(String keystr, byte[] contents) {
        if(keystr == null || contents == null)
            return null;

        SecretKeySpec keyspec = new SecretKeySpec(keystr.getBytes(), "AES");
        return encryptToString(keyspec, contents);
    }

    public static String encryptToString(SecretKey key, byte[] contents) {
        if(key == null || contents == null)
            return null;

        byte[] res = encryptToBytes(key, contents);
        if(res != null)
            return Base64.encodeBase64String(res);
        else
            return null;
    }

    public static byte[] decryptToBytes(String keystr, String str) {
        if(keystr == null || str == null)
            return null;

        SecretKeySpec keyspec = new SecretKeySpec(keystr.getBytes(), "AES");

        return decryptToBytes(keyspec, Base64.decodeBase64(str));
    }

    public static byte[] decryptToBytes(String keystr, byte[] contents) {
        if(keystr == null || contents == null)
            return null;

        SecretKeySpec keyspec = new SecretKeySpec(keystr.getBytes(), "AES");

        return decryptToBytes(keyspec, contents);
    }

    public static byte[] decryptToBytes(SecretKey key, String str) {
        if(key == null || str == null)
            return null;
        
        return decryptToBytes(key, Base64.decodeBase64(str));
    }

    public static byte[] decryptToBytes(SecretKey key, byte[] contents) {
        if(key == null || contents == null)
            return null;

        try {
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, key);
// TODO: do this           return cipher.doFinal(contents);
            return contents;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
    
    public static String decryptToString(String keystr, String str) {
        if(keystr == null || str == null)
            return null;

        SecretKeySpec keyspec = new SecretKeySpec(keystr.getBytes(), "AES");

        return decryptToString(keyspec, Base64.decodeBase64(str));
    }

    public static String decryptToString(String keystr, byte[] contents) {
        if(keystr == null || contents == null)
            return null;

        SecretKeySpec keyspec = new SecretKeySpec(keystr.getBytes(), "AES");

        return decryptToString(keyspec, contents);
    }

    public static String decryptToString(SecretKey key, String str) {
        if(key == null || str == null)
            return null;

        return decryptToString(key, Base64.decodeBase64(str));
    }

    public static String decryptToString(SecretKey key, byte[] contents) {
        if(key == null || contents == null)
            return null;

        byte[] res = decryptToBytes(key, contents);
        if(res != null)
            return new String(res);
        else
            return null;
    }

}
